#include "../../include/properties/Properties.h"


namespace Circle {

    Properties::Properties() : securityString("") {
        spdlog::debug("Properties object created.");
    }

    Properties::Properties(const std::string& filePath) : securityString("") {
        spdlog::debug("Properties object created from file: {}", filePath);
        if (isValid(filePath)) {
            loadFromFile(filePath);
        } else {
            spdlog::error("Invalid properties file: {}", filePath);
        }
    }

    Properties::~Properties() {
        spdlog::debug("Properties object destroyed.");
    }

    void Properties::loadFromFile(const std::string& filePath) {
        std::ifstream file(filePath);
        if (file.is_open()) {
            std::string line;
            while (std::getline(file, line)) {
                if (line.empty() || line[0] == '#') {
                    continue; // 跳过空行和注释行
                }
                size_t pos = line.find('=');
                if (pos != std::string::npos) {
                    std::string key = line.substr(0, pos);
                    std::string value = line.substr(pos + 1);
                    propertiesMap[key] = value;
                    spdlog::info("Loaded property from file: {} = {}", key, value);
                }
            }
            file.close();
        } else {
            spdlog::error("Unable to open file: {}", filePath);
        }
    }

    bool Properties::add(const std::string& key, const std::string& value) {
        if (securityString.empty() || SafetyValidation(key, securityString)) {
            spdlog::info("Adding property: {} = {}", key, value);
            propertiesMap[key] = value;
            return true;
        }
        spdlog::warn("Security validation failed for adding property: {}", key);
        return false;

    }

    bool Properties::remove(const std::string& key) {
        if (securityString.empty() || SafetyValidation(key, securityString)) {
            auto it = propertiesMap.find(key);
            if (it != propertiesMap.end()) {
                spdlog::info("Removing property: {}", key);
                propertiesMap.erase(it);
                return true;
            } else {
                spdlog::warn("Property {} not found for removal.", key);
            }
        } else {
            spdlog::warn("Security validation failed for removing property: {}", key);
        }
        return false;
    }

    bool Properties::set(const std::string& key, const std::string& value) {
        if (securityString.empty() || SafetyValidation(key, securityString)) {
            auto it = propertiesMap.find(key);
            if (it != propertiesMap.end()) {
                spdlog::info("Modifying property: {} = {}", key, value);
                it->second = value;
                return true;
            } else {
                spdlog::warn("Property {} not found for modification.", key);
            }
        } else {
            spdlog::warn("Security validation failed for modifying property: {}", key);
        }
        return false;
    }

    std::string Properties::get(const std::string& key) const {
        auto it = propertiesMap.find(key);
        if (it != propertiesMap.end()) {
            spdlog::info("Getting property: {} = {}", key, it->second);
            return it->second;
        }
        spdlog::warn("Property {} not found.", key);
        return "";
    }

    bool Properties::isValid(const std::string& filePath) {
        size_t pos = filePath.rfind(".properties");
        bool result = pos != std::string::npos && pos == filePath.length() - 11;
        spdlog::info("Checking file {} for validity: {}", filePath, result ? "valid" : "invalid");
        return result;
    }

    bool Properties::SafetyValidation(const std::string& key, const std::string& str) const {
        std::unordered_set<std::string> keys;
        std::stringstream ss(str);
        std::string token;

        while (std::getline(ss, token, '|')) {
            if (token.empty()) continue;
            keys.insert(token);
        }

        ss.clear();
        ss.str(str);
        while (std::getline(ss, token, ',')) {
            if (token.empty()) continue;
            keys.insert(token);
        }

        ss.clear();
        ss.str(str);
        while (std::getline(ss, token, ';')) {
            if (token.empty()) continue;
            keys.insert(token);
        }
        bool result = keys.find(key) == keys.end();
        if (!result) {
            // Use spdlog's formatting syntax
            spdlog::info("The value of {} is protected by security measures, and operations on it are not allowed.", key);
        }
        return result;
    }

    bool Properties::setSecurityString(const std::string& securityStr) {
        if (securityString.empty() || SafetyValidation(securityStr, securityString)) {
            securityString = securityStr;
            spdlog::info("Security string set to: {}", securityStr);
            return true;
        }
        spdlog::warn("Security validation failed for setting security string.");
        return false;
    }

    std::string Properties::getSecurityString() const {
        return securityString;
    }

} // namespace Circle